package com.blacktry.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.blacktry.convent.AdminConvert;
import com.blacktry.entity.model.ApiResult;
import com.blacktry.entity.model.Admin;
import com.blacktry.entity.model.ExamManage;
import com.blacktry.entity.model.Role;
import com.blacktry.entity.model.Vo.UserVo;
import com.blacktry.entity.model.request.AdminRequest;
import com.blacktry.entity.model.request.LoginRequest;
import com.blacktry.entity.model.request.PasswordRequest;
import com.blacktry.entity.model.request.UserRequest;
import com.blacktry.entity.model.vueVO.Option;
import com.blacktry.mapper.AdminMapper;
import com.blacktry.service.AdminService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.blacktry.service.RoleService;
import com.blacktry.utils.ApiResultHandler;
import com.blacktry.utils.JwtTokenUtil;
import com.github.xiaoymin.knife4j.core.util.StrUtil;
import io.netty.util.internal.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.ReactiveRedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author blackTry
 * @since 2021-06-23
 */
@Service
@Transactional
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {

    @Override
    public Integer insert(Admin admin) {
        admin.setPassword(passwordEncoder.encode(admin.getPassword()));
        return this.baseMapper.insert(admin);
    }

    @Override
//    @Cacheable(cacheNames = "selectById",unless = "#result==null")
    public Admin selectById(Integer id) {
        return this.baseMapper.selectById(id);
    }


    @Override
//    @CachePut(cacheNames = "selectByUsername",  key="'admin_'+#admin.username")
    public Integer insertOrUpdate(Admin admin) {
//        admin.setPassword(passwordEncoder.encode(admin.getPassword()));
        if (cn.hutool.core.util.StrUtil.isBlank(String.valueOf(admin.getId()))) {
            // 没有传入ID直接插入数据
            return this.baseMapper.insert(admin);
        } else {
            if (selectById(admin.getId()) == null) {
                // 导入数据的ID没有与表中的ID重复则插入数据
                return this.baseMapper.insert(admin);
            } else {
                // 传入的ID与表中已有的ID重复则更新数据
                return this.baseMapper.updateById(admin);
            }
        }
    }

    @Override
//    @Cacheable(cacheNames = "selectAdminPage",unless = "#result==null")
    public Page<Admin> selectAdminPage(AdminRequest adminRequest, Page<Admin> adminPage) {
        Admin admin = AdminConvert.INSTANCE.adminRequest2Admin(adminRequest);
        LambdaQueryWrapper<Admin> wrapper = new LambdaQueryWrapper<>();
        // 根据科目，班级，年级，描述，禁用条件查询
        if (admin.getId() != null) {
            wrapper.eq(Admin::getId, admin.getId());
        }
        if (admin.getName() != null) {
            wrapper.eq(Admin::getName, admin.getName());
        }
        if (admin.getPhone() != null) {
            wrapper.eq(Admin::getPhone, admin.getPhone());
        }
        if (admin.getTelephone() != null) {
            wrapper.like(Admin::getTelephone, admin.getTelephone());
        }

        if (admin.getAddress() != null) {
            wrapper.eq(Admin::getAddress, admin.getAddress());
        }
        if (admin.getUsername() != null) {
            wrapper.eq(Admin::getUsername, admin.getUsername());
        }
        if (admin.getPassword() != null) {
            wrapper.eq(Admin::getPassword, admin.getPassword());
        }
        if (admin.getUserFace() != null) {
            wrapper.eq(Admin::getUserFace, admin.getUserFace());
        }
        if (admin.getRemark() != null) {
            wrapper.eq(Admin::getRemark, admin.getRemark());
        }
        if (admin.getEmail() != null) {
            wrapper.eq(Admin::getEmail, admin.getEmail());
        }
        if (admin.getCardId() != null) {
            wrapper.eq(Admin::getCardId, admin.getCardId());
        }
        if (admin.getAffiliation() != null) {
            wrapper.eq(Admin::getAffiliation, admin.getAffiliation());
        }
        if (adminRequest.getFlag() != 2) {
            wrapper.eq(Admin::isEnabled, adminRequest.getFlag());
        }
        return this.baseMapper.selectPage(adminPage, wrapper);
    }

    @Override
    public Integer deleteBatchId(String[] ids) {
        List<String> idList = Arrays.asList(ids);
        return this.baseMapper.deleteBatchIds(idList);
    }

//    @Autowired
//    private RedisTemplate redisTemplate;
    @Override
//    unless = "#result==null"   表示查询出的结果为空时不进行缓存存储
//    @Cacheable(cacheNames = "selectByUsername",unless = "#result==null",key="'admin_'+#username")
    public Admin selectByUsername(String username) {

//        Object o=   redisTemplate.opsForValue().get("admin_"+username);
//        if(o!=null){
//            //    缓存中有数据从redis中获取
//            return (Admin) o;
//        }else{
            LambdaQueryWrapper<Admin> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Admin::getUsername, username).eq(Admin::isEnabled, 1);
             return this.baseMapper.selectOne(wrapper);
                //将数据设置到缓存中
//            redisTemplate.opsForValue().set("admin_"+b.getUsername(),b);


    }


    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Value("${jwt.tokenHead}")
    private String tokenHead;

    @Autowired
    private RoleService roleService;


    /**
     * 登陆之后返回token
     *
     * @param loginRequest
     * @param request
     * @return
     */
    @Override
    public ApiResult<Map<String, String>> login(LoginRequest loginRequest, HttpServletRequest request) {
        String captcha = (String) request.getSession().getAttribute("captcha");
        if (StrUtil.isBlank(loginRequest.getVerifyCode()) || !captcha.equalsIgnoreCase(loginRequest.getVerifyCode())) {
            return ApiResultHandler.buildApiResult(-1, "验证码输入错误,请重新输入!");
        }
        // 登录用户判断
        UserDetails userDetails = userDetailsService.loadUserByUsername(loginRequest.getUsername());
        if (null == userDetails || !passwordEncoder.matches(loginRequest.getPassword(), userDetails.getPassword())) {
            return ApiResultHandler.buildApiResult(-1, "用户名或者密码错误!");
        }
        if (!userDetails.isEnabled()) {
            return ApiResultHandler.buildApiResult(-1, "账号被禁用，请联系管理员!");
        }
        // 更新登录对象
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        // 生成对应token
        String token = jwtTokenUtil.generateToken(userDetails);
        Map<String, String> tokenMap = new HashMap<>();
        tokenMap.put("token", token);
        tokenMap.put("tokenHead", tokenHead);
        return ApiResultHandler.buildApiResult(200, "成功", tokenMap);
    }




    @Override
//    @Cacheable(cacheNames = "getAdminByUserName",unless = "#result==null")
    public Admin getAdminByUserName(String username) {
        QueryWrapper<Admin> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Admin::getUsername, username);
        Admin admin = this.baseMapper.selectOne(wrapper);
        return admin;
    }

    @Override
//    @Cacheable(cacheNames = "getRoles",unless = "#result==null")
    public List<Role> getRoles(Integer id) {
        return roleService.getRoles(id);
    }

    @Override

    public Boolean isRightPassword(Integer id, String password) {
        Admin admin = selectById(id);
        return passwordEncoder.matches(password, admin.getPassword());
    }

    @Override
//    @Cacheable(cacheNames = "selectPage", unless = "#result==null")
    public Page<Admin> selectPage(UserRequest userRequest, Page<Admin> adminPage) {
//        LambdaQueryWrapper<Admin> wrapper = new LambdaQueryWrapper<>();
        QueryWrapper<Admin> wrapper = new QueryWrapper<>();
        // 根据name,username,affiliation,competent,enable条件查询
        if (!StringUtil.isNullOrEmpty(userRequest.getName())) {
            wrapper.lambda().like(Admin::getName, userRequest.getName());
        }
        if (!StringUtil.isNullOrEmpty(userRequest.getUsername())) {
            wrapper.lambda().eq(Admin::getUsername, userRequest.getUsername());
        }
        if (!StringUtil.isNullOrEmpty(userRequest.getAffiliation())) {
            wrapper.lambda().eq(Admin::getAffiliation, userRequest.getAffiliation());
        }
        if (!StringUtil.isNullOrEmpty(userRequest.getCompetent())) {
            wrapper.lambda().eq(Admin::getCompetent, userRequest.getCompetent());
        }
        if (!StringUtil.isNullOrEmpty(userRequest.getEnabled())) {
            wrapper.eq("enabled", userRequest.getEnabled());
        }
        return this.baseMapper.selectPage(adminPage, wrapper);
    }

    @Override
    public Integer updateEnabled(Integer id, Integer enabled) {
        UpdateWrapper<Admin> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", id).set("enabled", enabled);
        return this.baseMapper.update(null, wrapper);
    }

    @Override
//    @Cacheable(cacheNames = "selectRole", unless = "#result==null")
    public Page<UserVo> selectRole(String role,Page<UserVo> page) {
        return this.baseMapper.selectRole(role,page);
    }

    @Autowired
    private AliOssServiceImpl aliOssService;

    @Override
    public String updateFace(MultipartFile file,String username) {
        // 获取现在的用户头像
        Admin admin = this.selectByUsername(username);
        // 标记删除旧头像
        aliOssService.deleteFile(admin.getUserFace());
        // 上传新头像
        admin.setUserFace(aliOssService.upload(file));
        this.insertOrUpdate(admin);
        return "新头像已上传成功";
    }

    @Override
    public Boolean updatePassword(PasswordRequest passwordRequest) {
        if(isRightPassword(passwordRequest.getId(),passwordRequest.getOldPass())){
            Admin admin = this.selectById(passwordRequest.getId());
            admin.setPassword(passwordEncoder.encode(passwordRequest.getPass()));
            this.updateById(admin);
            return true;
        }
        return false;
    }

    @Override
//    @Cacheable(cacheNames = "selectAllAffiliation", unless = "#result==null")
    public String[] selectAllAffiliation() {
        return this.baseMapper.selectAllAffiliation();
    }

    @Override
//    @Cacheable(cacheNames = "selectAllTeacher", unless = "#result==null")
    public List<Option> selectAllTeacher() {
        return this.baseMapper.selectAllTeacher();
    }

}
